package cn.bluethink.eguan.core.security;

import java.io.PrintWriter;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import cn.bluethink.eguan.core.service.EgUserService;
import cn.bluethink.eguan.model.core.EgCheckStatus;
import cn.bluethink.eguan.model.core.EgRole;
import cn.bluethink.eguan.model.core.EgUser;
import cn.bluethink.eguan.utils.TokenManager;

/**
 * @author GeoDev
 */
public class SecurityInterceptor extends HandlerInterceptorAdapter {

	private static final Logger logger = LoggerFactory.getLogger(SecurityManager.class);
	
    @Autowired
    private TokenManager tokenManager;
    
	@Autowired
    private EgUserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //return authorizationManager.handle(request, response, handler);
		if (handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			Method method = handlerMethod.getMethod();
			Token annotation = method.getAnnotation(Token.class);
			if (annotation != null) {
				String token = request.getHeader("Authorization");
				if (token != null && !("").equals(token) && !("unknown").equals(token)) {
					Long uid = tokenManager.verifyToken(token);
					if ( 0 == uid ) {
						return this.badAuthorizationInfo(request, response, UnauthorizedMessage.TOKEN_INVALIDATION);
					}
					request.setAttribute("userId", uid);
					EgUser user = userService.getUser(uid,true);
					if( user == null )
						return this.badAuthorizationInfo(request, response, UnauthorizedMessage.ACCOUNT_NULL);
					if ( user.getCheckStatus() == EgCheckStatus.STATUS_NOPASS )
						return this.badAuthorizationInfo(request, response, UnauthorizedMessage.LOCKED_ACCOUNT);
					
					int[] purviews = annotation.purviews();
					if (purviews != null && purviews.length > 0) {
						boolean hasPurview = false;
						EgRole role = user.getRole();
						for (int purview : purviews) {
							if ((role.getPurview() & purview) > 0) {
								hasPurview = true;
								break;
							}
						}
						if ( !hasPurview )
							return this.badAuthorizationInfo(request, response, UnauthorizedMessage.INADEQUATE_PERMISSIONS);
					}
					logger.info(user.getName()+"("+user.getId()+")用户身份认证成功！");
				}
				else {
					return this.badAuthorizationInfo(request, response, UnauthorizedMessage.MISSING_AUTHORIZATION_HEADER);
				}
			}
		}
		return true;
	}

	private boolean badAuthorizationInfo(HttpServletRequest request, HttpServletResponse response, UnauthorizedMessage message) throws Exception {
		logger.info(message.getMessage());

		JSONObject jsonObject = new JSONObject();
		jsonObject.put("status", message.getStatus());
		jsonObject.put("message", message.getMessage());

		PrintWriter writer = null;
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json");
		response.setHeader("Access-Control-Allow-Credentials", "true"); //是否支持cookie跨域
		response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
		response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
		response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
		try {
			writer = response.getWriter();
			String json = JSON.toJSONString(jsonObject);
			writer.print(json);
		} finally {
			if (writer != null) {
				writer.close();
			}
		}
		return false;
	}
}